﻿using PeiYue.AuthHelper;
using PeiYue.Common;
using PeiYue.Common.AppConfig;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using PeiYue.AuthHelper.Policys;

namespace PeiYue.Extensions
{
    /// <summary>
    /// JWT权限 认证服务
    /// </summary>
    public static class Authentication_JWTSetup
    {
        public static void AddAuthentication_JWTSetup(this IServiceCollection services)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));


            var symmetricKeyAsBase64 = AppSecretConfig.Audience_Secret_String;
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var Issuer = Appsettings.app(new string[] { "Audience", "Issuer" });
            var Audience = Appsettings.app(new string[] { "Audience", "Audience" });

            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = Issuer,//发行人
                ValidateAudience = true,
                ValidAudience = Audience,//订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromSeconds(30),
                RequireExpirationTime = true,
            };

            // 开启Bearer认证
            services.AddAuthentication(o=> {
                o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme = nameof(ApiResponseHandler);
                o.DefaultForbidScheme = nameof(ApiResponseHandler);
            })
             // 添加JwtBearer服务
             .AddJwtBearer(o =>
             {
                 o.TokenValidationParameters = tokenValidationParameters;
                 o.Events = new JwtBearerEvents
                 {
                     OnChallenge = context =>
                     {
                         context.Response.Headers.Add("Token-Error", context.ErrorDescription);
                         return Task.CompletedTask;
                     },
                     OnAuthenticationFailed = context =>
                     {
                         var token= context.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "");
                         var jwtToken = (new JwtSecurityTokenHandler()).ReadJwtToken(token);
                         //string exp = jwtToken.Claims.Where(t => t.Type == System.Security.Claims.ClaimTypes.Expiration).Select(t => t.Value).FirstOrDefault();
                         //Common.LogHelper.SerilogServer.WriteLog("exp" + DateTime.Now.ToString("yyyyMMdd"), new string[] { exp });
                         //if (!string.IsNullOrWhiteSpace(exp))
                         //{
                         //    var dto = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(exp));
                         //    var dt = dto.ToLocalTime().DateTime;
                         //    var tokenExp = Convert.ToInt32(Appsettings.app(new string[] { "TokenExpiration" }));
                         //    if (dt.AddMinutes(tokenExp) <= DateTime.Now)
                         //    {
                         //        context.Response.Headers.Add("Token-Expired", "true");
                         //        context.Response.ContentType = "application/json";
                         //        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                         //        context.Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE401)).MessageModel));
                         //        return Task.CompletedTask;
                         //    }
                         //}

                         if (jwtToken.Issuer != Issuer)
                         {
                             context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!");
                         }
                         if (jwtToken.Audiences.FirstOrDefault() != Audience)
                         {
                             context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
                         }

                        
                         // 如果过期，则把<是否过期>添加到，返回头信息中
                         if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         {
                             Common.LogHelper.SerilogServer.WriteLog("TokenExpired" + DateTime.Now.ToString("yyyyMMdd"), new string[] { token });
                             context.Response.Headers.Add("Token-Expired", "true");
                             context.Response.ContentType = "application/json";
                             context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                             context.Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE401)).MessageModel));
                             return Task.CompletedTask;
                         }
                         return Task.CompletedTask;
                     }
                 };
             })
             .AddScheme<AuthenticationSchemeOptions, ApiResponseHandler>(nameof(ApiResponseHandler), o => { });

        }
    }
}
